﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace AgileTimeTracker.Client.Wpf.Common
{
    public class BaseViewModel : INotifyPropertyChanged
    {
        private bool isBusy;
        private string busyMessage;
        private string title;

        public event PropertyChangedEventHandler PropertyChanged;

        public event EventHandler IsBusyChanged;

        public BaseViewModel()
        {
            this.InititalizeCommands();
            this.InitializeLists();
            this.PropertyChanged += HandlePropertyChanged;
        }

        public string Title
        {
            get { return this.title; }
            set { this.OnPropertyChanged(ref this.title, value); }
        }

        public bool IsBusy
        {
            get { return this.isBusy; }
            set
            {
                if (this.isBusy == value)
                {
                    return;
                }

                this.isBusy = value;
                this.OnPropertyChanged("IsBusy");
                this.OnIsBusyChanged();
            }
        }

        public string BusyMessage
        {
            get { return this.busyMessage; }
            set { this.OnPropertyChanged(ref this.busyMessage, value); }
        }

        public RelayCommand LoadCommand { get; set; }

        protected void OnPropertyChanged<TVal>(ref TVal propVal, TVal newVal, [CallerMemberName]string propertyName = null)
        {
            if (!object.Equals(propVal, newVal))
            {
                propVal = newVal;
                this.OnPropertyChanged(propertyName);
            }
        }

        protected void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        protected void OnIsBusyChanged()
        {
            if (this.IsBusyChanged != null)
            {
                this.IsBusyChanged(this, EventArgs.Empty);
            }
        }

        protected void BlockUi(string message = null)
        {
            this.BusyMessage = message ?? "Wait...";
            this.IsBusy = true;
        }

        protected void UnblockUi()
        {
            this.IsBusy = false;
            this.BusyMessage = null;
        }

        protected virtual void Load()
        {
        }

        protected virtual void InititalizeCommands()
        {
            this.LoadCommand = new RelayCommand(this.Load);
        }

        protected virtual void InitializeLists()
        {
        }

        protected virtual void HandlePropertyChanged(object sender, PropertyChangedEventArgs e)
        {
        }

        protected void GlueBusyInfo(BaseViewModel childViewModel)
        {
            if (childViewModel == null)
            {
                return;
            }

            this.UnglueBusyInfo(childViewModel);
            childViewModel.PropertyChanged += this.ChildViewModelPropertyChanged;
        }

        protected void UnglueBusyInfo(BaseViewModel childViewModel)
        {
            if (childViewModel == null)
            {
                return;
            }

            childViewModel.PropertyChanged -= this.ChildViewModelPropertyChanged;
        }

        private void ChildViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            var childViewModel = sender as BaseViewModel;
            switch (e.PropertyName)
            {
                case "IsBusy":
                    this.IsBusy = childViewModel.IsBusy;
                    break;
                case "BusyMessage":
                    this.BusyMessage = childViewModel.BusyMessage;
                    break;
            }
        }
    }
}
